﻿using System;
using System.Collections.Generic;
using System.Text;

using System.IO;
using System.Reflection;
using System.Xml;
namespace ScpControl 
{
    public enum Ds3PadId :   byte { None = 0xFF, One = 0x00, Two = 0x01, Three = 0x02, Four = 0x03, All = 0x04 };

   
    public class DebugEventArgs   : EventArgs 
    {
        protected DateTime m_Time = DateTime.Now;
        protected String m_Data = String.Empty;

        public DebugEventArgs(String Data) 
        {
            m_Data = Data;
        }

        public DateTime Time 
        {
            get { return m_Time; }
        }

        public String Data 
        {
            get { return m_Data; }
        }
    }

    public class ReportEventArgs  : EventArgs 
    {
        protected Ds3PadId m_Pad = Ds3PadId.None;
        protected Byte[] m_Report = new Byte[64];

        public ReportEventArgs() 
        {
        }

        public ReportEventArgs(Ds3PadId Pad) 
        {
            m_Pad = Pad;
        }

        public Ds3PadId Pad 
        {
            get { return m_Pad; }
            set { m_Pad = value; }
        }

        public Byte[] Report 
        {
            get { return m_Report; }
        }
    }

    public class Global
    {
        protected static BackingStore m_Config = new BackingStore();

        protected static Int32 m_IdleTimeout = 600000;

        //BetterDS4 {
        public static ledColor loadPlayerColor1(int device) {
            ledColor color = new ledColor();
            color.red = m_Config.m_Leds[device][0];
            color.green = m_Config.m_Leds[device][1];
            color.blue = m_Config.m_Leds[device][2];
            return color;
        }

        public static ledColor loadPlayerColor2(int device) {
            ledColor color = new ledColor();
            color.red = m_Config.m_Leds[device][3];
            color.green = m_Config.m_Leds[device][4];
            color.blue = m_Config.m_Leds[device][5];
            return color;
        }

        public static ledColor loadBatteryColor1(int device) {
            ledColor color = new ledColor();
            color.red = m_Config.m_Leds[device][6];
            color.green = m_Config.m_Leds[device][7];
            color.blue = m_Config.m_Leds[device][8];
            return color;
        }

        public static ledColor loadBatteryColor2(int device) {
            ledColor color = new ledColor();
            color.red = m_Config.m_Leds[device][9];
            color.green = m_Config.m_Leds[device][10];
            color.blue = m_Config.m_Leds[device][11];
            return color;
        }

        public static int getCurrentMappings(int device, int input)
        {
            return m_Config.currentMappings[device][input];
        }
        public static void setCurrentMappings(int device, int input, int setting)
        {
            m_Config.currentMappings[device][input] = setting;
            Save();
        }
        //Better DS4 }

        public static byte loadRumbleBoost(int device)
        {
            return m_Config.m_Rumble[device];
        }

        public static bool getFlushHIDQueues()
        {
            return m_Config.flushHIDQueues;
        }
        public static void setFlushHIDQueues(bool setting)
        {
            m_Config.flushHIDQueues = setting;
            Save();
        }

        public static byte getTouchSensitivity(int device)
        {
            return m_Config.touchSensitivity[device];
        }
        public static void setTouchSensitivity(int device, byte sen)
        {
            m_Config.touchSensitivity[device] = sen;
            Save();
        }

        //BetterDS4 {
        public static void savePlayerColor1(int device, byte red, byte green, byte blue) {
            m_Config.m_Leds[device][0] = red;
            m_Config.m_Leds[device][1] = green;
            m_Config.m_Leds[device][2] = blue;
            Save();
        }
        public static void savePlayerColor2(int device, byte red, byte green, byte blue) {
            m_Config.m_Leds[device][3] = red;
            m_Config.m_Leds[device][4] = green;
            m_Config.m_Leds[device][5] = blue;
            Save();
        }
        public static void saveBatteryColor1(int device, byte red, byte green, byte blue) {
            m_Config.m_Leds[device][6] = red;
            m_Config.m_Leds[device][7] = green;
            m_Config.m_Leds[device][8] = blue;
            Save();
        }
        public static void saveBatteryColor2(int device, byte red, byte green, byte blue)
        {
            m_Config.m_Leds[device][9] = red;
            m_Config.m_Leds[device][10] = green;
            m_Config.m_Leds[device][11] = blue;
            Save();
        }
        public static void setProfile(int device, string profile)
        {
            m_Config.m_ProfileName[device] = profile;
            LoadProfile(device);
            Save();
        }

        public static string getProfile(int device)
        {
            return m_Config.m_ProfileName[device];
        }
        //BetterDS4 }

        public static void saveRumbleBoost(int device, byte boost)
        {
            m_Config.m_Rumble[device] = boost;
            Save();

        }

        public static byte getFlashPercentage(int device) {
            return m_Config.flashPercentage[device];
        }

        public static void setFlashPercentage(int device, byte percentage) {
            m_Config.flashPercentage[device] = percentage;
            Save();
        }

        public static void setFlashWhenLowBattery(int device, bool flash) {
            m_Config.flashLedLowBattery[device] = flash;
            Save();
        }

        public static bool getFlashWhenLowBattery(int device)
        {
            return m_Config.flashLedLowBattery[device];
        }


        public static void setLedAsBatteryIndicator(int device, bool ledAsBattery)
        {
            m_Config.ledAsBattery[device] = ledAsBattery;
            Save();

        }
        public static bool getLedAsBatteryIndicator(int device)
        {
            return m_Config.ledAsBattery[device];

        }

        public static void setTouchEnabled(int device, bool touchEnabled)
        {
            m_Config.touchEnabled[device] = touchEnabled;
            Save();

        }
        public static bool getTouchEnabled(int device)
        {
            return m_Config.touchEnabled[device];

        }

        public static void setDeviceSharingModeIsExclusive(bool value)
        {
            m_Config.deviceSharingModeIsExclusive = value;
            HidLibrary.HidDevice.deviceSharingModeIsExclusive = value;
            Save();
        }
        public static bool getDeviceSharingModeIsExclusive()
        {
            return m_Config.deviceSharingModeIsExclusive;
        }

        public static void Load() 
        {
            m_Config.Load();
        }

        public static void Save() 
        {
            m_Config.Save();
        }

        // XXX still fugly color transition, fix the algorithm
        private static byte applyRatio(byte b1, byte b2, uint r)
        {
            uint ratio = r;
            if (b1 > b2)
            {
                ratio = 100 - r;
            }
            // We get 10%-100% as input but 0% would have the controller off and thus not be useful, so remap the values.
            ratio = ratio * 9 / 10; //BetterDS4
            byte bmax = Math.Max(b1, b2);
            byte bmin = Math.Min(b1, b2);
            byte bdif = (byte)(bmax - bmin);
            return (byte)(bmin + (bdif * ratio / 100));
        }

        public static ledColor getTransitionedColor(ledColor c1, ledColor c2, int deviceNum, uint ratio)
        {
            uint r = ratio % 101;
            ledColor color = new ledColor();
            color.red = applyRatio(c2.red, c1.red, r);
            color.green = applyRatio(c2.green, c1.green, r);
            color.blue = applyRatio(c2.blue, c1.blue, r);

            return color;
        }



        protected static Profile m_Profile = new Profile();

        public static void LoadProfile(int device)
        {
            m_Config.currentMappings[device] = m_Profile.Load(m_Config.m_ProfileName[device]);
        }

        public static void SaveProfile(int device, string profile)
        {
            m_Config.m_ProfileName[device] = profile;
            m_Profile.Save(profile, m_Config.currentMappings[device]);
        }

    }

    public class Profile
    {
        protected String m_File = @"Profiles\XBox 360.ds4";
        protected XmlDocument m_Xdoc = new XmlDocument();
        
        public int[] Load(string p)
        {
            int[] m_Mapping = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };

            try
            {

                m_File = @"Profiles\"+p+".ds4";

                XmlNode Item;

                if (!File.Exists(m_File))
                {
                    m_File = Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName +"\\"+ m_File;
                }
                m_Xdoc.Load(m_File);

                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/Y"); int.TryParse(Item.InnerText, out m_Mapping[0]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/B"); int.TryParse(Item.InnerText, out m_Mapping[1]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/A"); int.TryParse(Item.InnerText, out m_Mapping[2]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/X"); int.TryParse(Item.InnerText, out m_Mapping[3]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/Start"); int.TryParse(Item.InnerText, out m_Mapping[4]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/Select"); int.TryParse(Item.InnerText, out m_Mapping[5]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/Guide"); int.TryParse(Item.InnerText, out m_Mapping[6]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/L1"); int.TryParse(Item.InnerText, out m_Mapping[7]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/L2"); int.TryParse(Item.InnerText, out m_Mapping[8]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/R1"); int.TryParse(Item.InnerText, out m_Mapping[9]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/R2"); int.TryParse(Item.InnerText, out m_Mapping[10]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/Up"); int.TryParse(Item.InnerText, out m_Mapping[11]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/Right"); int.TryParse(Item.InnerText, out m_Mapping[12]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/Down"); int.TryParse(Item.InnerText, out m_Mapping[13]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/Left"); int.TryParse(Item.InnerText, out m_Mapping[14]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/LeftStickX"); int.TryParse(Item.InnerText, out m_Mapping[15]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/LeftStickY"); int.TryParse(Item.InnerText, out m_Mapping[16]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/RightStickX"); int.TryParse(Item.InnerText, out m_Mapping[17]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/RightStickY"); int.TryParse(Item.InnerText, out m_Mapping[18]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/L3"); int.TryParse(Item.InnerText, out m_Mapping[19]); }
                catch { }
                try { Item = m_Xdoc.SelectSingleNode("/BetterDS4/Mapping/R3"); int.TryParse(Item.InnerText, out m_Mapping[20]); }
                catch { }
            }
            catch { }

            return m_Mapping;
        }

        public Boolean Save(string p, int[] m)
        {
            m_File = @"Profiles\"+p+".ds4";
            
            Boolean Saved = true;

            try
            {
                XmlNode Node, Entry;

                m_Xdoc.RemoveAll();

                Node = m_Xdoc.CreateXmlDeclaration("1.0", "utf-8", String.Empty);
                m_Xdoc.AppendChild(Node);

                Node = m_Xdoc.CreateComment(String.Format(" BetterDS4 v1.2", DateTime.Now));
                m_Xdoc.AppendChild(Node);

                Node = m_Xdoc.CreateWhitespace("\r\n");
                m_Xdoc.AppendChild(Node);

                Node = m_Xdoc.CreateNode(XmlNodeType.Element, "BetterDS4", null);

                XmlNode mNode = m_Xdoc.CreateNode(XmlNodeType.Element, "Mapping", null); Node.AppendChild(mNode);

                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "Y", null); Entry.InnerText = m[0].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "B", null); Entry.InnerText = m[1].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "A", null); Entry.InnerText = m[2].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "X", null); Entry.InnerText = m[3].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "Start", null); Entry.InnerText = m[4].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "Select", null); Entry.InnerText = m[5].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "Guide", null); Entry.InnerText = m[6].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "L1", null); Entry.InnerText = m[7].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "L2", null); Entry.InnerText = m[8].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "R1", null); Entry.InnerText = m[9].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "R2", null); Entry.InnerText = m[10].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "Up", null); Entry.InnerText = m[11].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "Right", null); Entry.InnerText = m[12].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "Down", null); Entry.InnerText = m[13].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "Left", null); Entry.InnerText = m[14].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "LeftStickX", null); Entry.InnerText = m[15].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "LeftStickY", null); Entry.InnerText = m[16].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "RightStickX", null); Entry.InnerText = m[17].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "RightStickY", null); Entry.InnerText = m[18].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "L3", null); Entry.InnerText = m[19].ToString(); mNode.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "R3", null); Entry.InnerText = m[20].ToString(); mNode.AppendChild(Entry);

                m_Xdoc.AppendChild(Node);

                m_Xdoc.Save(m_File);
            }
            catch { Saved = false; }

            return Saved;
        }
    }

    public class BackingStore
    {
        protected String m_File = @"ScpControl.xml";
        protected XmlDocument m_Xdoc = new XmlDocument();

        public bool deviceSharingModeIsExclusive = true;
        public bool flushHIDQueues = false;
        //Better DS4 {
        public Byte[][] m_Leds = new Byte[][] // per-controller nominal color and low-battery color
        {
            new Byte[] {0,0,255, 0,0,2, 0,255,0, 255,0,0},
            new Byte[] {255,0,0, 2,0,0, 0,255,0, 255,0,0},
            new Byte[] {0,255,0, 0,2,0, 0,255,0, 255,0,0},
            new Byte[] {127,0,127, 1,0,1, 0,255,0, 255,0,0},
        };

        public int[][] currentMappings = new int[][] {
            new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 },
            new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 },
            new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 },
            new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 },
        };

        public string[] m_ProfileName = { "XBox 360", "XBox 360", "XBox 360", "XBox 360" };

        //Better DS4 }
        public Byte[] m_Rumble = { 100, 100, 100, 100 };
        public bool[] ledAsBattery = { true, true, true, true };
        public bool[] flashLedLowBattery = { false, false, false, false };
        public Byte[] flashPercentage = { 20, 20, 20, 20 };
        public Byte[] touchSensitivity = { 100, 100, 100, 100 };
        public bool[] touchEnabled = { false, false, false, false };
        public Boolean Load()
        {
            Boolean Loaded = true;

            try
            {
                XmlNode Item;

                if (!File.Exists(m_File))
                    m_File = Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName + @"\ScpControl.xml";
                m_Xdoc.Load(m_File);

                try { Boolean.TryParse(m_Xdoc.SelectSingleNode("/ScpControl/deviceSharingModeIsExclusive").InnerText, out deviceSharingModeIsExclusive); }
                catch { }

                try { Boolean.TryParse(m_Xdoc.SelectSingleNode("/ScpControl/flushHIDQueues").InnerText, out flushHIDQueues); }
                catch { }

                HidLibrary.HidDevice.deviceSharingModeIsExclusive = deviceSharingModeIsExclusive;

                for (int i = 0; i < 4; i++)
                {
                    //Player Color 1
                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/PlayerColorR"); Byte.TryParse(Item.InnerText, out m_Leds[i][0]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/PlayerColorG"); Byte.TryParse(Item.InnerText, out m_Leds[i][1]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/PlayerColorB"); Byte.TryParse(Item.InnerText, out m_Leds[i][2]); }
                    catch { }

                    //Player Color 2
                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/PlayerColor2R"); Byte.TryParse(Item.InnerText, out m_Leds[i][3]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/PlayerColor2G"); Byte.TryParse(Item.InnerText, out m_Leds[i][4]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/PlayerColor2B"); Byte.TryParse(Item.InnerText, out m_Leds[i][5]); }
                    catch { }

                    //Battery Color 1
                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/BatteryColorR"); Byte.TryParse(Item.InnerText, out m_Leds[i][6]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/BatteryColorG"); Byte.TryParse(Item.InnerText, out m_Leds[i][7]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/BatteryColorB"); Byte.TryParse(Item.InnerText, out m_Leds[i][8]); }
                    catch { }

                    //Battery Color 2
                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/BatteryColor2R"); Byte.TryParse(Item.InnerText, out m_Leds[i][9]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/BatteryColor2G"); Byte.TryParse(Item.InnerText, out m_Leds[i][10]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/BatteryColor2B"); Byte.TryParse(Item.InnerText, out m_Leds[i][11]); }
                    catch { }



                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/RumbleBoost"); Byte.TryParse(Item.InnerText, out m_Rumble[i]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/ledAsBatteryIndicator"); Boolean.TryParse(Item.InnerText, out ledAsBattery[i]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/lowBatteryFlash"); Boolean.TryParse(Item.InnerText, out flashLedLowBattery[i]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/flashPercentage"); Byte.TryParse(Item.InnerText, out flashPercentage[i]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/touchSensitivity"); Byte.TryParse(Item.InnerText, out touchSensitivity[i]); }
                    catch { }

                    try { Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/touchEnabled"); Boolean.TryParse(Item.InnerText, out touchEnabled[i]); }
                    catch { }

                    try {
                        Item = m_Xdoc.SelectSingleNode("/ScpControl/Controller" + (i + 1) + "/Profile");
                        m_ProfileName[i] = Item.InnerText;
                    }
                    catch { }

                    try
                    {
                        string[] files = { "Profiles" };

                        if (Directory.Exists("Profiles"))
                        {

                            files = Directory.GetFiles("Profiles");

                            for (int ii = 0; ii < files.Length; ii++)
                            {
                                files[ii] = (files[ii]).Replace(@"Profiles\", "").Replace(".ds4", "");
                                if (files[ii] == Global.getProfile(i))
                                {
                                    Global.setProfile(i, Global.getProfile(i));
                                }
                            }
                        }
                        else
                        {
                            Directory.CreateDirectory("Profiles");
                        }
                    }
                    catch { }

                }

            }
            catch { Loaded = false; }

            return Loaded;
        }

        public Boolean Save()
        {
            Boolean Saved = true;

            try
            {
                XmlNode Node, Entry;

                m_Xdoc.RemoveAll();

                Node = m_Xdoc.CreateXmlDeclaration("1.0", "utf-8", String.Empty);
                m_Xdoc.AppendChild(Node);

                Node = m_Xdoc.CreateComment(String.Format(" ScpControl Configuration Data. {0} ", DateTime.Now));
                m_Xdoc.AppendChild(Node);

                Node = m_Xdoc.CreateWhitespace("\r\n");
                m_Xdoc.AppendChild(Node);

                Node = m_Xdoc.CreateNode(XmlNodeType.Element, "ScpControl", null);

                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "deviceSharingModeIsExclusive", null); Entry.InnerText = deviceSharingModeIsExclusive.ToString(); Node.AppendChild(Entry);
                Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "flushHIDQueues", null); Entry.InnerText = flushHIDQueues.ToString(); Node.AppendChild(Entry);
                XmlNode cNode1 = m_Xdoc.CreateNode(XmlNodeType.Element, "Controller1", null); Node.AppendChild(cNode1);
                XmlNode cNode2 = m_Xdoc.CreateNode(XmlNodeType.Element, "Controller2", null); Node.AppendChild(cNode2);
                XmlNode cNode3 = m_Xdoc.CreateNode(XmlNodeType.Element, "Controller3", null); Node.AppendChild(cNode3);
                XmlNode cNode4 = m_Xdoc.CreateNode(XmlNodeType.Element, "Controller4", null); Node.AppendChild(cNode4);

                XmlNode[] cNodes = { cNode1, cNode2, cNode3, cNode4 };

                for (int i = 0; i < 4; i++)
                {
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "PlayerColorR", null); Entry.InnerText = m_Leds[i][0].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "PlayerColorG", null); Entry.InnerText = m_Leds[i][1].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "PlayerColorB", null); Entry.InnerText = m_Leds[i][2].ToString(); cNodes[i].AppendChild(Entry);

                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "PlayerColor2R", null); Entry.InnerText = m_Leds[i][3].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "PlayerColor2G", null); Entry.InnerText = m_Leds[i][4].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "PlayerColor2B", null); Entry.InnerText = m_Leds[i][5].ToString(); cNodes[i].AppendChild(Entry);

                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "BatteryColorR", null); Entry.InnerText = m_Leds[i][6].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "BatteryColorG", null); Entry.InnerText = m_Leds[i][7].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "BatteryColorB", null); Entry.InnerText = m_Leds[i][8].ToString(); cNodes[i].AppendChild(Entry);

                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "BatteryColor2R", null); Entry.InnerText = m_Leds[i][9].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "BatteryColor2G", null); Entry.InnerText = m_Leds[i][10].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "BatteryColor2B", null); Entry.InnerText = m_Leds[i][11].ToString(); cNodes[i].AppendChild(Entry);

                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "RumbleBoost", null); Entry.InnerText = m_Rumble[i].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "ledAsBatteryIndicator", null); Entry.InnerText = ledAsBattery[i].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "lowBatteryFlash", null); Entry.InnerText = flashLedLowBattery[i].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "flashPercentage", null); Entry.InnerText = flashPercentage[i].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "touchSensitivity", null); Entry.InnerText = touchSensitivity[i].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "touchEnabled", null); Entry.InnerText = touchEnabled[i].ToString(); cNodes[i].AppendChild(Entry);
                    Entry = m_Xdoc.CreateNode(XmlNodeType.Element, "Profile", null); Entry.InnerText = m_ProfileName[i]; cNodes[i].AppendChild(Entry);

                }
                m_Xdoc.AppendChild(Node);

                m_Xdoc.Save(m_File);
            }
            catch { Saved = false; }

            

            return Saved;
        }
    }
}
